package com.kwin.rpcserver.netty.worker;

import javax.annotation.PreDestroy;

import com.kwin.rpcserver.netty.code.JSONDecoder;
import com.kwin.rpcserver.netty.code.JSONEncoder;
import com.kwin.rpcserver.netty.handler.NettyServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;

/**
 * @author : wangkai
 * @version V1.0
 * @Package com.kwin.rpcserver.netty.worker
 * @Description:
 * @date 2021年07月30日 16:09
 **/
@Slf4j
public class RpcServer {
    
    private EventLoopGroup bossGroup = new NioEventLoopGroup();
    private EventLoopGroup workerGroup = new NioEventLoopGroup();
    
    private int port;
    
    private int idleTime;
    
    public RpcServer(int port, int idleTime) {
        this.port = port;
        this.idleTime = idleTime;
    }
    
    public void start() throws InterruptedException {
        final NettyServerHandler handler = new NettyServerHandler();
        new Thread(() -> {
            try {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.group(bossGroup, workerGroup).
                    channel(NioServerSocketChannel.class).
                    localAddress(new InetSocketAddress(port)).
                    option(ChannelOption.SO_BACKLOG, 1024).
                    childOption(ChannelOption.SO_KEEPALIVE, true).
                    childOption(ChannelOption.TCP_NODELAY, true).
                    childHandler(new ChannelInitializer<SocketChannel>() {
                        //创建NIOSocketChannel成功后，在进行初始化时，将它的ChannelHandler设置到ChannelPipeline中，用于处理网络IO事件
                        @Override
                        protected void initChannel(SocketChannel channel) throws Exception {
                            ChannelPipeline pipeline = channel.pipeline();
                            pipeline.addLast(new IdleStateHandler(idleTime, 0, 0));
                            pipeline.addLast(new JSONEncoder());
                            pipeline.addLast(new JSONDecoder());
                            pipeline.addLast(handler);
                        }
                    });
             
                ChannelFuture cf = bootstrap.bind().sync();
                log.info("RPC 服务器启动.监听端口: {}", port);
                
                // 服务注册 TODO:
//                registry.register(serverAddress);
                //等待服务端监听端口关闭
                cf.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }).start();
    }
    
    
    /**
     * 销毁
     */
    @PreDestroy
    public void close() {
        bossGroup.shutdownGracefully().syncUninterruptibly();
        workerGroup.shutdownGracefully().syncUninterruptibly();
        log.info("关闭 Netty 成功");
    }
}
